const express = require("express");
const path = require("path");
// const http = require("http");
const https = require("https");
const fs = require("fs");
const app = express();

const privateKey = fs.readFileSync("../../Nginx_SSL/2_hongbin.xyz.key", "utf8");
const certificate = fs.readFileSync(
  "../../Nginx_SSL/1_hongbin.xyz_bundle.crt",
  "utf8"
);
const credentials = { key: privateKey, cert: certificate };

// const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);

const port = process.env.PORT || 3000;
const server = httpsServer.listen(port);
// const server = app.listen(port);
const io = require("socket.io")(server, { cors: true });
//服务端发送 客户端接收
const EVENT = {
  SEND_MESSAGE: "SEND_MESSAGE",
  CONNECT: "connect",
  DISCONNECT: "disconnect",
  ERROR: "connect_error",
  WELCOME: "WELCOME",
  ANNOUNCEMENT: "announcement",
  BROADCAST_NEW_GAMER: "BROADCAST_NEW_GAMER",
  BROADCAST_LEAVE_THE_GAME: "BROADCAST_LEAVE_THE_GAME",
  FIGHT: "FIGHT",
  REJECTED_FIGHT: "REJECTED_FIGHT",
  ACCEPTED_FIGHT: "ACCEPTED_FIGHT",
  SHOULD_GO: "SHOULD_GO",
  PLAYED_CHESS: "PLAYED_CHESS",
  WINED: "WINED", //接受这条消息的是败北的一方
};
//客户端发送 服务端接收
const EMIT = {
  ENTER: "ENTER",
  LEAVE_THE_GAME: "LEAVE_THE_GAME",
  FIGHT_REQUEST: "FIGHT_REQUEST",
  REJECT_FIGHT: "REJECT_FIGHT",
  ACCEPT_FIGHT: "ACCEPT_FIGHT",
  PLAY_CHESS: "PLAY_CHESS",
  WIN: "WIN",
};

const allGamers = {};

io.on(EVENT.CONNECT, socket => {
  console.log("连接成功");
  socket.on(EMIT.ENTER, name => {
    socket.nickname = name;
    //收到玩家进入返回当前所有在线人
    socket.emit(EVENT.WELCOME, JSON.stringify(allGamers));
    allGamers[name] = socket.id;
    console.log("enter name:" + name);
    //发布通知 新玩家进入
    console.log("广播: " + name);
    console.log("所有人:", allGamers);
    const newGame = { name, allGamers };
    socket.broadcast.emit(EVENT.BROADCAST_NEW_GAMER, JSON.stringify(newGame));
  });
  //接收 客户端发送的请求 给目标客户端发送对战邀请
  socket.on(EMIT.FIGHT_REQUEST, payload => {
    const { target, message, nickname } = JSON.parse(payload);
    console.log("target:", nickname + "send " + message);
    const fightData = { nickname, message, socketId: socket.id };
    socket.to(target).emit(EVENT.FIGHT, JSON.stringify(fightData));
  });
  //接收 客户端发送的请求 给目标客户端发送拒绝对战
  socket.on(EMIT.REJECT_FIGHT, target => {
    const payload = { nickname: socket.nickname, socketId: socket.id };
    socket.to(target).emit(EVENT.REJECTED_FIGHT, JSON.stringify(payload));
  });
  //接收 客户端发送的请求 给目标客户端发送接受对战
  socket.on(EMIT.ACCEPT_FIGHT, target => {
    const payload = { nickname: socket.nickname, socketId: socket.id };
    socket.to(target).emit(EVENT.ACCEPTED_FIGHT, JSON.stringify(payload));
    //通知两人 该谁下了
    socket.to(target).emit(EVENT.SHOULD_GO, socket.nickname);
    socket.emit(EVENT.SHOULD_GO, socket.nickname);
  });
  //接收 客户端发送的请求 给目标客户端发送落子的位置
  socket.on(EMIT.PLAY_CHESS, payload => {
    const { index, socketId, nickname } = JSON.parse(payload);
    //告诉另一人 棋子的下标
    const data = JSON.stringify({ index, nickname: socket.nickname });
    socket.to(socketId).emit(EVENT.PLAYED_CHESS, data);
    //落完一次子再通知两人 该谁下了
    socket.to(socketId).emit(EVENT.SHOULD_GO, nickname);
    socket.emit(EVENT.SHOULD_GO, nickname);
  });
  //接收 客户端发送的请求 给目标客户端发送败北消息
  socket.on(EMIT.WIN, target => {
    socket.to(target).emit(EVENT.WINED);
  });
  //断开连接
  socket.on(EVENT.DISCONNECT, () => {
    const nickname = socket.nickname;
    console.log(nickname + "关闭了连接");
    delete allGamers[nickname];
    //broadcast 用户离线广播
    socket.broadcast.emit(EVENT.BROADCAST_LEAVE_THE_GAME, nickname);
  });
});

app.use("/", (req, res, next) => {
  let pathName = req.url;
  console.log(pathName);
  // 提供一个 icon就不会发起/favicon.ico的请求了
  if (pathName == "/") {
    pathName = "/index.html";
  }

  const extName = path.extname(pathName);
  fs.readFile(`../client/build${pathName}`, function (err, data) {
    if (err) {
      console.error(err);
      res.status(400).json(err);
    } else {
      const ext = getExt(extName);
      res.writeHead(200, { "Content-Type": ext + "; charset=utf-8" });
      res.write(data);
    }
    res.end();
  });
});

// 获取后缀名
getExt = extName => {
  switch (extName) {
    case ".html":
      return "text/html";
    case ".css":
      return "text/css";
    case ".js":
      return "text/js";
    case ".ico":
      return "image/x-icon";
    case ".png":
      return "image/png";
    default:
      return "text/html";
  }
};
